﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace WsProtocol.PublicClass
{
    //协议框架基类
    public abstract class PtlBase
    {
        public PtlInformation ptlinfo;
        public PtlBase TransPtl;  //转发的协议
        public abstract string GetCorrectFrame(string aframe, ref string errinfo);  //从收到的返回帧中获取正确格式的帧   

        public abstract string GetFrameWithoutUpload(ref string aframe, ref string errinfo);  //从收到的返回帧中获取正确格式的帧，过滤掉主动上传的
        public abstract int ResolveFrame(string recframe, ref string errinfo);  //将收到的返回帧分拆到类中
        public abstract string CreateOrder(string RWflag, int maxlength, ref string errinfo);  //生成指令
        public abstract string CreateRandom(string RWflag, string pardata, int maxlength, ref string errinfo);  //生成任意指令
        public abstract string CreateNextOrder(ref string errinfo);  //生成续抄指令
        public abstract int AnalizeFrame(ref string errinfo);  //解析
        public abstract string CompareFrame(string sendstr, string recstr, string WRflag, int datalength);  //判断收发帧是否匹配
        public abstract string GetData();  //获取数据域，用于有后续帧时将所有数据域拼起来
        public abstract string GetRealData();  //获取真实数据域，通常指解密后的数据
        public abstract void SetData(string sdata);  //设置数据域，用于将拼起来的数据域拿回来
        public abstract string CalcCS(string sdata);  //计算校验
        public abstract string GetResult();  //获取设参结果
        public abstract string GetReadValue();  //获取解析后的值，所有值拼起来，逗号分隔
        public abstract string GetFrameValue();  //获取解析前的原始值，所有值拼起来，逗号分隔
        public abstract bool NeedReturn();  //判断当前指令是否需要返回 
        public abstract string GetPRM();  //获取启动标志  1:下行   0:上行  shaunwang 2019-8-19


        /// <summary>
        /// 从收到的返回帧中获取正确格式的帧  多个帧用,分割
        /// </summary>
        /// <param name="aframe">原始数据</param>
        /// <param name="errinfo">错误信息</param>
        /// <returns>正确帧</returns>
        public virtual string GetCorrectFrameLst(string aframe, ref string errinfo) //
        {
            string rs = "";
            string err =  "";
            while (!string.IsNullOrEmpty(aframe)) 
            {
                err = "";
                string rec = GetCorrectFrame(aframe, ref err);
                if (string.IsNullOrEmpty(err) && !string.IsNullOrEmpty(rec)) //取到正确帧了 
                {
                    rs += rec
                        + ",";
                    int p = aframe.IndexOf(rec);
                    aframe = aframe.Substring(p + rec.Length);
                }
                else
                    break;
              
            }
            if (rs.EndsWith(","))
                rs = rs.Substring(0, rs.Length - 1);  //去掉结尾的逗号

            if (string.IsNullOrEmpty(rs))  //啥都没取到
                errinfo = err;
            return rs;
        }
    }

    //协议信息类
    public class PtlInformation
    {
        public int Ptlid { get; set; }  //协议类别
        public string IfCorrect { get; set; }  //正常  异常标志
        public string specialCH { get; set; }  //分隔符
        public string ProtocolName { get; set; }  //协议名称
        public string DataName { get; set; } //当前操作的协议数据名称
        public string SendFrame { get; set; }  //发送原始帧，保存生成的指令
        public string Frame { get; set; }  //原始帧，下发时保存生成的指令，解析时保存收到的帧
        public string ContinueOrder { get; set; }  //续抄指令
        public string ConfirmOrder { get; set; }  //确认帧，用于处理主动上报  2019-8-19  shaunwang 
        public string ExpectLength { get; set; }  //理论数据长度
        public string SendFunc { get; set; }  //发送特殊处理函数名
        public string RecFunc { get; set; }  //接收特殊处理函数名
        public string AnaFunc { get; set; }  //解析后的特殊处理函数名
        public bool AnaDone { get; set; }  //本次是否已解析

        private Hashtable TmpData { get; set; } //用于存放临时数据的缓冲区

        public PtlInformation()
        {
            AnaDone = false;
            TmpData = new Hashtable();
            DataName = string.Empty;
        } 

        /// <summary>
        /// 存储临时数据
        /// </summary>
        /// <param name="skey">关键字</param>
        /// <param name="sdata">数据</param>
        public void AddTmpData(string skey, string sdata) 
        {
            if (!TmpData.ContainsKey(skey))
                TmpData.Add(skey, "");
            TmpData[skey] += sdata;
        }

        /// <summary>
        /// 获取临时数据
        /// </summary>
        /// <param name="skey"></param>
        /// <returns></returns>
        public string GetTmpData(string skey)
        {
            string rs = string.Empty;
            if (TmpData.ContainsKey(skey))
                rs = (string)TmpData[skey];
            return rs;
        }

        /// <summary>
        /// 移除临时数据
        /// </summary>
        /// <param name="skey">关键字</param>
        public void RemoveTmpData(string skey)
        {
            if (TmpData.ContainsKey(skey))
                TmpData.Remove(skey);
        }

        /// <summary>
        /// 清空临时数据
        /// </summary>
        public void RemoveTmpData()
        {
            TmpData.Clear();
        }
    }

    //协议格式类
    public abstract class PtlFormat
    {
        public abstract List<string> GetInfo();  //获取分解后的描述信息
        public abstract void FetchFrame(string frame);  //将完整的帧分解到结构
        public abstract void AddInformation(Hashtable arghments);  //添加格式信息
        public abstract void AddFormat(object objformat);  //添加解析格式
    }
}
